#ifndef __DTINTERVAL_
#define __DTINTERVAL_

#include "bool_interval.h"
#include "interval_from_real.h"
#include "interval.h"
#include <cassert>


class DTInterval {
public:
    DTInterval(Interval i, BoolInterval def);

    Interval unsafeI() const;
    BoolInterval def() const;

    inline double unsafeA() const {
        return unsafeI().unsafeA();
    }
    inline double unsafeB() const {
        return unsafeI().unsafeB();
    }

    BoolInterval lt(const DTInterval& that) const;
    inline BoolInterval gt(const DTInterval& that) const {
        return that.lt(*this);
    }
    BoolInterval eq(const DTInterval& that) const;

    // 重载<和>
    BoolInterval operator<(const DTInterval& that) const;
    inline BoolInterval operator>(const DTInterval& that) const {
        return that<(*this);
    }

    DTInterval sqrt() const;
    DTInterval isin() const;
    DTInterval icos() const;
    DTInterval itan() const;
    DTInterval ilog() const;

    DTInterval& operator+=(const DTInterval& that);
    DTInterval& operator-=(const DTInterval& that);
    DTInterval& operator*=(const DTInterval& that);
    DTInterval& operator/=(const DTInterval& that);
    DTInterval operator^( const int& x);

    DTInterval& operator++();
    inline DTInterval operator++(int) {
        DTInterval old(*this);
        operator++();
        return old;
    }

    DTInterval& operator--();
    inline DTInterval operator--(int) {
        DTInterval old(*this);
        operator--();
        return old;
    }

    friend void swap(DTInterval& a, DTInterval& b);
    friend bool operator==(const DTInterval& l, const DTInterval& r);

private:
    Interval i_;
    BoolInterval def_;
    void assertInvariant() const;
};

template<>
inline DTInterval intervalFromReals<DTInterval>(double a, double b) {
    return DTInterval(forceInterval(a, b), alltrue);  //一个具有良好定义的区间
}

inline DTInterval operator+(DTInterval l, const DTInterval& r) {
  l += r;
  return l;
}
inline DTInterval operator-(DTInterval l, const DTInterval& r) {
  l -= r;
  return l;
}
inline DTInterval operator*(DTInterval l, const DTInterval& r) {
  l *= r;
  return l;
}
inline DTInterval operator/(DTInterval l, const DTInterval& r) {
  l /= r;
  return l;
}

#endif
